package terminal;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.TreeSet;

import pagemaker.ExternalProgramException;
import pagemaker.MuPDFPageMaker;
import domain.PDFLibrary;
import domain.PDFdoc;
import ut.Log;

public class Terminal {

    private static PDFLibrary   lib;
    private static List<PDFdoc> currentGroup;
    private static InfoLine     il;
    private static int          ccounter = 1;
    private static PDFdoc       currentDoc;

    private static void initializeApplication() {

        if (ut.OsUtils.isWindows()) {
            Log.setLogFile("c:\\temp\\DCOdocTerminal.log");
            MuPDFPageMaker.setProgram("c:\\utils\\mupdf\\mudraw.exe");
            MuPDFPageMaker.setCacheDirectory("c:\\temp\\pdfpages\\");
        } else if (ut.OsUtils.isLinux()) {
            Log.setLogFile("/tmp/DCOdoc.log");
            MuPDFPageMaker.setProgram("/usr/bin/pdfdraw");
            MuPDFPageMaker.setCacheDirectory("/home/tl/pdfpages/");
        }
        // Example of library initialization
        lib = PDFLibrary.makePDFLibrary("pdf-db.txt");
        lib.loadLibrary();
        lib.setGroupSize(10);
        currentGroup = lib.getFirstGroup();
        il = new InfoLine();
    }

    private static void printInfoLine() {
        il.setLeft("" + lib.selectionSize() + "/" + lib.getNumberOfDocuments()
                + " documents.");
        System.out.println(il);
    }

    private static ArrayList<String> stringToTags(String s) {
        ArrayList<String> tags = new ArrayList<String>();
        String[] at = s.split(",");
        for (int i = 0; i < at.length; i++) {
            String t = at[i].toUpperCase().trim();
            if (t.length() > 0) {
                tags.add(t);
            }
        }
        return tags;
    }

    private static void displaySelection() {
        if (currentGroup != null) {
            for (PDFdoc doc : currentGroup) {
                if (currentDoc != null && currentDoc.equals(doc)) System.out
                        .printf(">> %3d", doc.getDocumentNumber());
                else
                    System.out.printf("   %3d", doc.getDocumentNumber());
                System.out.println(". " + doc.getTitle() + " ["
                        + doc.tagsToString(",") + "]");
            }
        } else {
            Log.prt("in AppPanel.displaySelection: currentSelection is null.");
        }
        Log.prt("in AppPanel.displaySelection: done.");
        Log.prt("group " + (lib.getCurrentGroupNumber() + 1) + "/"
                + lib.nbGroupsInSelection());
        il.setCenter("group " + (lib.getCurrentGroupNumber() + 1) + "/"
                + lib.nbGroupsInSelection());
    }

    private static void displayCurrentDoc() {
        if (currentDoc != null) {
            System.out.printf(">> %3d", currentDoc.getDocumentNumber());
            System.out.println(". " + currentDoc.getTitle() + " ["
                    + currentDoc.tagsToString(",") + "]");
        }
    }

    private static void printPrompt() {
        System.out.print(ccounter + "> ");
        ccounter++;
    }

    private static void interactionLoop(Scanner keyboard) {
        boolean exit = false;
        String command;
        String[] scommand;
        boolean showList = true;
        ArrayList<String> currentTags = new ArrayList<String>();

        do {
            if (showList) displaySelection();
            else
                displayCurrentDoc();
            printInfoLine();
            printPrompt();
            command = keyboard.nextLine();
            command = command.trim();
            scommand = command.split(" ");
            if (command.startsWith("exit")) exit = true;
            if (command.startsWith("quit")) exit = true;
            if (command.startsWith("help")) help(scommand);
            if (command.startsWith("next")) currentGroup = lib.getNextGroup();
            if (command.startsWith("previous"))
                currentGroup = lib.getPreviousGroup();

            if (command.startsWith("select tags")) {
                if (command.length() <= command.indexOf("tags") + 5) {
                    currentTags = new ArrayList<String>();
                    // lib.selectDocsWithOneOfTheseTags(currentTags);
                    lib.selectDocsWithAllTheseTags(currentTags);
                    currentGroup = lib.getFirstGroup();
                    il.setRight("Current Tags: " + "[all]");
                } else {
                    String userTags = command
                            .substring(command.indexOf("tags") + 5);
                    currentTags.addAll(stringToTags(userTags));
                    // lib.selectDocsWithOneOfTheseTags(currentTags);
                    lib.selectDocsWithAllTheseTags(currentTags);
                    currentGroup = lib.getFirstGroup();
                    il.setRight("Current Tags: " + currentTags);
                }
            }
            if (command.startsWith("reset tags")) {
                currentTags = new ArrayList<String>();
                // lib.selectDocsWithOneOfTheseTags(currentTags);
                lib.selectDocsWithAllTheseTags(currentTags);
                currentGroup = lib.getFirstGroup();
                il.setRight("Current Tags: " + "[all]");
            }
            if (command.startsWith("select doc")) {
                String sdocn = scommand[scommand.length - 1];
                int docn = Integer.parseInt(sdocn);
                currentDoc = findDoc(docn, currentGroup);
                showList = false;
            }
            if (command.startsWith("view")) {
                if (currentDoc != null) {
                    try {
                        System.out.println(currentDoc.getCurrentPage());
                    } catch (IOException | ExternalProgramException e) {
                        e.printStackTrace();
                    }
                    il.setCenter("p. " + currentDoc.getCurrentPageNumber()
                            + "/" + currentDoc.getNumberOfPages());
                }
            }
            if (command.startsWith("np") || command.startsWith("next page")) {
                if (currentDoc != null) {
                    showList = false;
                    try {
                        System.out.println(currentDoc.getNextPage());
                    } catch (IOException | ExternalProgramException e) {
                        e.printStackTrace();
                    }
                    il.setCenter("p. " + currentDoc.getCurrentPageNumber()
                            + "/" + currentDoc.getNumberOfPages());
                }
            }
            if (command.startsWith("previous page") || command.startsWith("pp")) {
                if (currentDoc != null) {
                    showList = false;
                    try {
                        System.out.println(currentDoc.getPreviousPage());
                    } catch (IOException | ExternalProgramException e) {
                        e.printStackTrace();
                    }
                    il.setCenter("p. " + currentDoc.getCurrentPageNumber()
                            + "/" + currentDoc.getNumberOfPages());
                }
            }
            if (command.startsWith("document list")
                    || command.startsWith("documents")) showList = true;
            if (command.startsWith("set group size")) {
                String ssize = scommand[scommand.length - 1];
                int size = Integer.parseInt(ssize);
                lib.setGroupSize(size);
                currentGroup = lib.getFirstGroup();
            }
            if (command.startsWith("edit tags")) {
                if (currentDoc != null) {
                    System.out.println("Current tags are: "
                            + currentDoc.tagsToString(","));
                    System.out
                            .println("Enter new tag list (comma separated) : ");
                    String tags = keyboard.nextLine();
                    currentDoc.addTags(tags, ",");
                }
            }
            if (command.startsWith("edit title")) {
                if (currentDoc != null) {
                    System.out.println("Current title is: "
                            + currentDoc.getTitle());
                    System.out.println("Enter new title : ");
                    String title = keyboard.nextLine();
                    currentDoc.setTitle(title);
                }
            }
            if (command.startsWith("new doc")) {
                PDFdoc newDoc = null;
                try {
                    scommand[2] = scommand[2].trim();
                    if (scommand[2].endsWith("\n"))
                        scommand[2] = scommand[2].substring(0, scommand[2]
                                .lastIndexOf("\n") - 1);
                    if (new File(scommand[2]).exists()) {
                        System.err.println("File: " + scommand[2]);
                        newDoc = PDFdoc.makePDFdoc(new File(scommand[2]));
                        lib.addDoc(newDoc);
                        System.out
                                .println("Enter tag list (comma separated) : ");
                        String tags = keyboard.nextLine();
                        newDoc.addTags(tags, ",");
                        currentTags = stringToTags(tags);
                        // lib.selectDocsWithOneOfTheseTags(currentTags);
                        lib.selectDocsWithAllTheseTags(currentTags);
                        currentGroup = lib.getFirstGroup();
                        il.setRight("Current Tags: " + stringToTags(tags));
                        currentDoc = newDoc;
                        showList = true;
                    } else {
                        System.err.println("File: not found");
                        System.err.println("");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (ExternalProgramException e) {
                    e.printStackTrace();
                }
            }
            if (command.startsWith("remove doc")) {
                lib.removeDoc(currentDoc);
            }
        } while (!exit);
        lib.saveLibrary();
    }

    private static PDFdoc findDoc(int docn, List<PDFdoc> currentGroup) {
        PDFdoc theDoc = null;
        for (PDFdoc d : currentGroup) {
            if (d.getDocumentNumber() == docn) theDoc = d;
        }
        return theDoc;
    }

    private static void help(String[] scommand) {
        System.out
                .println("exit, quit ..................... Exit Application.");
        System.out.println("help ........................... Commands help.");
        System.out
                .println("next ........................... Display next group of documents.");
        System.out
                .println("previous ....................... Display previous group of documents.");
        System.out
                .println("set group size <n> ............. Set the number of documents that are shown in document lists.");
        System.out
                .println("select doc <n> ................. Select document <n> as the current document.");
        System.out
                .println("select tags <tag1> <tags2> ..... Select the documents that have the corresponding tags. ");
        System.out
                .println("reset tags ..................... Forget the last tag filter.");
        System.out
                .println("new doc <path> ................. Add a document to the library.");
        System.out
                .println("edit tags ...................... Edit current document's tags.");
        System.out
                .println("edit title ..................... Edit current document's title.");
        System.out
                .println("documents ...................... Show the current grupo of documents.");
        System.out
                .println("remove doc ..................... Removes current document from the library.");
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        initializeApplication();
        Scanner keyboard = new Scanner(System.in);
        interactionLoop(keyboard);

    }

}
